﻿using System;
using System.Linq;
using System.Collections.Generic;
using Light.Framework.Model;
using Light.Framework.Castle;
using NHibernate.Criterion;
using Light.Framework.Contract;
using Castle.ActiveRecord;
using System.Security.Permissions;
using System.Text;
using System.Data;
using Light.Utility;
using System.Data.Common;

namespace Light.Framework.Component
{
    /// <summary>
    /// 组件基类（包含通用的CRUD方法）
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BaseComponent<T> where T : class, IEntity, new()
    {

        private ModelOrder modelOrder = new ModelOrder();
        private List<string> orderFields = new List<string>();
        private Dictionary<string, string> searchFields = new Dictionary<string, string>();

        /// <summary>
        /// 查询字段属性
        /// </summary>
        public virtual Dictionary<string, string> SearchFields
        {
            get
            {
                if (searchFields.Count == 0)
                {
                    T obj = new T();
                    Dictionary<string, string> dic = obj.GetSearchFields();
                    if (dic != null && dic.Keys.Count > 0)
                    {
                        searchFields = dic;
                    }
                }
                return searchFields;
            }
        }

        /// <summary>
        /// 排序字段
        /// </summary>
        public virtual List<string> OrderFields
        {
            get
            {
                if (orderFields.Count == 0)
                {
                    T obj = new T();
                    Dictionary<string, string> dic = obj.GetOrderFields();
                    if (dic != null && dic.Keys.Count > 0)
                    {
                        searchFields = dic;
                    }
                }
                return orderFields;
            }
        }

        /// <summary>
        /// 排序对象
        /// </summary>
        public virtual ModelOrder ModelOrder
        {
            get { return modelOrder; }
            set { modelOrder = value; }
        }


        #region 基本的CRUD方法

        //[AccessSecurity(SecurityAction.Demand)]
        public virtual OperateResult Create(T obj)
        {
            OperateResult result = new OperateResult();

            if (obj.TimeCreated == default(DateTime))
                obj.TimeCreated = DateTime.Now;
            if (obj.TimeUpdated == default(DateTime))
                obj.TimeUpdated = DateTime.Now;
            if (obj.Organization == null)
            {
                obj.Organization = ServerApplication.User.Organization;
            }

            result = ValidateData(obj);
            if (!result.IsSucced)
            {
                return result;
            }

            int countExits = EntityMediator<T>.Count(CreateCriterion(obj));
            if (countExits > 0)
            {
                result.IsSucced = false;
                result.Message = GetExistMessage(obj);
            }
            else
            {
                result = Excute(EntityMediator<T>.Create, obj, OperateType.Create);
            }

            return result;
        }


        [AccessSecurity(SecurityAction.Demand)]
        public virtual OperateResult Delete(int id)
        {
            OperateResult result = new OperateResult() { IsSucced = false };
            T obj = Get(id);
            return Delete(obj);
        }

        //[AccessSecurity(SecurityAction.Demand)]
        public virtual OperateResult Update(T obj)
        {
            OperateResult result = new OperateResult();

            obj.TimeUpdated = DateTime.Now;
            if (obj.Organization == null)
            {
                obj.Organization = ServerApplication.User.Organization;
            }

            result = ValidateData(obj);
            if (!result.IsSucced)
            {
                return result;
            }

            int countExits = EntityMediator<T>.Count(Expression.And(CreateCriterion(obj), Expression.Not(Expression.Eq("ID", obj.ID))));
            if (countExits > 0)
            {
                result.IsSucced = false;
                result.Message = GetExistMessage(obj);
            }
            else
            {
                result = Excute(EntityMediator<T>.Update, obj, OperateType.Update);
            }
            return result;

        }

        [AccessSecurity(SecurityAction.Demand)]
        public virtual OperateResult Save(T obj)
        {
            if (obj.ID > 0)
            {

                return Update(obj);
            }
            else
            {
                return Create(obj);
            }
        }

        /// <summary>
        /// 验证数据（是否符合业务逻辑）
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual OperateResult ValidateData(T obj)
        {
            return new OperateResult() { IsSucced = true };
        }


        [AccessSecurity(SecurityAction.Demand)]
        public virtual OperateResult Delete(T obj)
        {
            OperateResult result = new OperateResult() { IsSucced = false };
            if (obj == null)
                result.Message = "没有符合条件的记录！";
            else
            {
                obj.IsDeleted = true;
                obj.TimeUpdated = DateTime.Now;
                result = Excute(EntityMediator<T>.Delete, obj, OperateType.Delete);
            }
            return result;
        }

        public virtual OperateResult Delete(IList<T> models)
        {
            OperateResult result = new OperateResult();

            bool isSucceed = true;
            if (models == null || models.Count == 0)
            {
                isSucceed = false;
                result.Message = "要删除的记录不能为空！";
            }
            else
            {
                StringBuilder builder = new StringBuilder();

                foreach (var model in models)
                {
                    result = Delete(model);
                    if (result.IsSucced == false)
                    {
                        isSucceed = false;
                        builder.Append(result.Message);
                    }
                }
                result.Message = builder.ToString();
            }
            result.IsSucced = isSucceed;

            return result;
        }


        [AccessSecurity(SecurityAction.Demand)]
        public virtual T Get(int id)
        {
            T model = null;
            try
            {
                model = EntityMediator<T>.Find(id);
                ServerApplication.Evit(model);
            }
            catch (Exception ex)
            {
                ServerApplication.Logger.LogError("试图获取一个不存在实体，ID：" + id.ToString() + " " + ex.Message);
            }

            return model;
        }

        [AccessSecurity(SecurityAction.Demand)]
        public virtual T Get()
        {
            return new T();
        }

        /// <summary>
        /// 不区分组织机构
        /// </summary>
        /// <returns></returns>
        [AccessSecurity(SecurityAction.Demand)]
        public virtual IList<T> GetAll()
        {
            IList<T> models = GetAll(GetCriterion(null));
            ServerApplication.Evit(models);
            return models;

        }

        [AccessSecurity(SecurityAction.Demand)]
        public virtual IList<T> GetAll(SearchArgs args)
        {
            ICriterion criterion = GetCriterion(args);

            return GetAll(criterion);
        }


        /// <summary>
        /// 根据条件返回一条记录
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public virtual T Get(SearchArgs args)
        {
            DetachedCriteria dc = null;

            if (args != null)
                dc = args.ToDetachedCriteria<T>();

            if (dc == null)
                throw new CustomException("查询条件不能为空");

            dc.Add(GetNotDeletedCriterion());
            T obj = EntityMediator<T>.FindFirst(dc);

            ServerApplication.Evit(obj);

            return obj;

        }

        /// <summary>
        /// 根据属性值获取单个实体
        /// </summary>
        /// <param name="propertyName"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public virtual T Get(string propertyName, object value)
        {
            ICriterion criterion = Expression.And(Expression.Eq(propertyName, value), GetNotDeletedCriterion());
            T obj = EntityMediator<T>.FindFirst(criterion);
            ServerApplication.Evit(obj);

            return obj;
        }

        /// <summary>
        /// 搜索
        /// </summary>
        /// <param name="args"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="totalResult"></param>
        /// <returns></returns>
        //[AccessSecurity(SecurityAction.Demand)]
        //public virtual IList<T> Search(SearchArgs args, int pageIndex, int pageSize, out int totalResult)
        //{

        //    ICriterion criterion = GetCriterion(args);

        //    return Search(criterion, pageIndex, pageSize, out totalResult);
        //}

        /// <summary>
        /// 搜索：支持关联查询
        /// </summary>
        /// <param name="args"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="totalResult"></param>
        /// <returns></returns>
        public virtual IList<T> Search(SearchArgs args, int pageIndex, int pageSize, out int totalResult)
        {

            DetachedCriteria criterion = GetDetachedCriteria(args);
            return Search(criterion, pageIndex, pageSize, out totalResult);
        }


        public virtual IList<T> Search(SearchArgs searchArgs, PageArgs pageArgs)
        {

            int totalResult = pageArgs.TotalResults;

            //ICriterion criterion = GetCriterion(searchArgs);
            DetachedCriteria criterion = GetDetachedCriteria(searchArgs);

            IList<T> result = Search(criterion, pageArgs.PageIndex, pageArgs.PageSize, out totalResult);

            pageArgs.TotalResults = totalResult;

            return result;
        }


        public virtual DataTable SearchTable(SearchArgs searchArgs, PageArgs pageArgs)
        {

            int totalResult = pageArgs.TotalResults;

            //ICriterion criterion = GetCriterion(searchArgs);
            DetachedCriteria criterion = GetDetachedCriteria(searchArgs);

            IList<T> result = Search(criterion, pageArgs.PageIndex, pageArgs.PageSize, out totalResult);

            pageArgs.TotalResults = totalResult;

            if (result != null)
                return DataTableHelper.ToDisplayTable<T>(result.ToArray());
            else
                return null;
        }

        public virtual int Count()
        {
            ICriterion criterion = Expression.Sql("1=1");
            return Count(criterion);
        }

        public virtual int Count(SearchArgs searchArgs)
        {

            //ICriterion criterion = GetCriterion(searchArgs);
            DetachedCriteria criterion = GetDetachedCriteria(searchArgs);

            return Count(criterion);
        }

        protected virtual IList<T> Search(ICriterion criterion, int pageIndex, int pageSize, out int totalResult)
        {
            using (TransactionScope ts = new TransactionScope())
            {
                try
                {
                    IList<T> models = null;

                    int totalPages = 0;

                    if (criterion != null)
                    {
                        models = EntityMediator<T>.SlicedFindAll(ref pageIndex, out totalPages, out totalResult, pageSize, ModelOrder.Orders, criterion);
                    }
                    else
                    {
                        models = EntityMediator<T>.SlicedFindAll(ref pageIndex, out totalPages, out totalResult, pageSize, ModelOrder.Orders);
                    }

                    ts.VoteCommit();
                    return models;
                }

                catch (Exception ex)
                {
                    ts.VoteRollBack();
                    ServerApplication.Logger.LogError(ex.Message);
                    throw ex;

                }
            }

        }

        protected virtual IList<T> Search(DetachedCriteria criterion, int pageIndex, int pageSize, out int totalResult)
        {
            using (TransactionScope ts = new TransactionScope())
            {
                try
                {
                    IList<T> models = null;

                    int totalPages = 0;

                    if (criterion != null)
                    {
                        models = EntityMediator<T>.SlicedFindAll(ref pageIndex, out totalPages, out totalResult, pageSize, ModelOrder.Orders, criterion);
                    }
                    else
                    {
                        models = EntityMediator<T>.SlicedFindAll(ref pageIndex, out totalPages, out totalResult, pageSize, ModelOrder.Orders);
                    }

                    ts.VoteCommit();
                    return models;
                }

                catch (Exception ex)
                {
                    ts.VoteRollBack();
                    ServerApplication.Logger.LogError(ex.Message);
                    throw ex;

                }
            }

        }


        /// <summary>
        /// 查询条件（附加组织机构过滤条件）
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        protected virtual ICriterion GetCriterion(SearchArgs args)
        {


            ICriterion criterion = null;

            if (args != null)
                criterion = args.ToCriterion<T>();
            if (criterion == null)
                criterion = Expression.Sql("1=1");
            //if (!ServerApplication.User.IsSuper)
            if (!ServerApplication.User.IsSuper || (ServerApplication.Organization!=null&&!ServerApplication.Organization.IsSystem))
            {

                IOrganizationComponent comp = ServerApplication.ComponentFactory.Create<IOrganizationComponent>();
                IList<Organization> list = comp.GetSubOrganization(ServerApplication.Organization, true);

                if (list.Count == 1)
                    criterion = Expression.And(criterion, Expression.Eq("Organization", list[0]));
                else
                    criterion = Expression.And(criterion, Expression.In("Organization", list.ToArray()));
            }

            if (!ServerApplication.User.IsSuper
                || (ServerApplication.User is User) && ((User)ServerApplication.User).IsApprole)
            {
                criterion = Expression.And(criterion, GetNotDeletedCriterion());
            }

            return criterion;
        }

        /// <summary>
        /// 查询条件（附加组织机构过滤条件）
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        protected virtual DetachedCriteria GetDetachedCriteria(SearchArgs args)
        {
            DetachedCriteria dc = null;

            if (args != null)
                dc = args.ToDetachedCriteria<T>();
            if (dc == null)
            {
                dc = DetachedCriteria.For<T>();
                dc = dc.Add(Expression.Sql("1=1"));
            }
            //if (!ServerApplication.User.IsSuper)
            //超级管理员或系统用户查看所有信息
            if (!ServerApplication.User.IsSuper || (ServerApplication.Organization != null && !ServerApplication.Organization.IsSystem))
            {

                IOrganizationComponent comp = ServerApplication.ComponentFactory.Create<IOrganizationComponent>();
                IList<Organization> list = comp.GetSubOrganization(ServerApplication.Organization, true);
                ICriterion criterion = null;

                if (list.Count == 1)
                    criterion = Expression.Eq("Organization", list[0]);
                else
                    criterion = Expression.In("Organization", list.ToArray());
                dc.Add(criterion);
            }
            if (!ServerApplication.User.IsSuper
                || (ServerApplication.User is User) && ((User)ServerApplication.User).IsApprole)
            {
                dc.Add(GetNotDeletedCriterion());
            }
            return dc;

        }

        /// <summary>
        /// 执行增，删，改操作
        /// </summary>
        /// <param name="method">方法名</param>
        /// <param name="data">操作对象</param>
        /// <param name="type">操作类型</param>
        /// <returns></returns>
        protected OperateResult Excute(Action<T> method, T data, OperateType type)
        {
            OperateResult result = new OperateResult();
            try
            {
                if (data.IsValidated == false)
                {
                    result.IsSucced = false;
                    result.Message = data.GetErrorMessage();

                    return result;
                }
                switch (type)
                {
                    case OperateType.Create: result.Message = "添加失败！"; break;
                    case OperateType.Update: result.Message = "更新失败！"; break;
                    case OperateType.Delete: result.Message = "删除失败！"; break;
                    default: break;
                }

                using (TransactionScope ts = new TransactionScope())
                {
                    try
                    {
                        method(data);
                        ts.VoteCommit();
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                        ts.VoteRollBack();
                    }


                }
                result.IsSucced = true;
                string optStr = string.Empty;

                switch (type)
                {
                    case OperateType.Create: result.Message = "添加成功！"; break;
                    case OperateType.Update: result.Message = "更新成功！"; break;
                    case OperateType.Delete: result.Message = "删除成功！"; break;
                    default: break;
                }

                bool traceable = ReflectionHelper.HasAttribute<TraceableAttribute>(typeof(T));
                if (traceable)
                {
                    string name = ReflectionHelper.GetAttributeValue<TraceableAttribute>(typeof(T), "Name");
                    if (String.IsNullOrEmpty(name))
                    {
                        name = ReflectionHelper.GetDisplayName(typeof(T));
                    }
                    string message = string.Format("{0}【{1}】{2} 操作人：{3}", name, data.ToString(), result.Message, ServerApplication.User != null ? ServerApplication.User.Name : "系统");
                    ServerApplication.Logger.LogOperation(message);
                }
            }
            catch (Exception ex)
            {

                result.IsSucced = false;

                if (ex.InnerException != null && ex.InnerException.InnerException != null)
                {
                    result.Message = ex.InnerException.InnerException.Message;
                    if (result.Message.ToUpper().Contains("FOREIGN KEY"))
                    {
                        //result.Message = " 数据正在使用中，" + result.Message;
                        result.Message = " 数据正在使用中,请先删除其他相关信息！";
                    }
                }
                else if (ex.InnerException != null)
                {
                    result.Message += " 错误详细：" + ex.InnerException.Message;
                }
                else
                {
                    result.Message += " 错误详细：" + ex.Message;
                }

                ServerApplication.Logger.LogError(result.Message);
            }

            return result;
        }

        [AccessSecurity(SecurityAction.Demand)]
        protected virtual IList<T> GetAll(ICriterion criterion)
        {
            IList<T> models = null;
            if (criterion == null)
            {
                models = EntityMediator<T>.FindAll();
            }
            else
            {
                models = EntityMediator<T>.FindAll(ModelOrder.Orders, criterion);
            }

            ServerApplication.Evit<T>(models);

            return models;

        }

        protected virtual int Count(ICriterion criterion)
        {
            int count = 0;
            if (criterion == null)
            {
                count = EntityMediator<T>.Count();
            }
            else
            {
                count = EntityMediator<T>.Count(criterion);
            }
            return count;
        }

        protected virtual int Count(DetachedCriteria dc)
        {
            int count = 0;
            if (dc == null)
            {
                count = EntityMediator<T>.Count();
            }
            else
            {
                count = EntityMediator<T>.Count(dc);
            }
            return count;
        }

        #endregion


        #region 批量导入

        /// <summary>
        /// 批量导入时分批次保存每批次的数量
        /// </summary>
        protected int SizePerBatch = 50;

        /// <summary>
        /// 导入
        /// </summary>
        /// <param name="models"></param>
        /// <returns></returns>
        public virtual OperateResult Import(List<T> models)
        {
            OperateResult result = Validate(models.ToArray());

            if (result.IsSucced)
            {
                #region 导入至DB

                int cntSucced = 0;
                int cntFailed = 0;

                int pageIndex = 1;

                StringBuilder builder = new StringBuilder();
                using (TransactionScope ts = new TransactionScope())
                {
                    try
                    {


                        List<T> tmpModels = GetByPage(models, pageIndex, SizePerBatch);
                        while (tmpModels != null && tmpModels.Count > 0)
                        {

                            //1.创建一个大的查询条件
                            ICriterion groupCriterion = null;
                            foreach (var model in tmpModels)
                            {
                                if (groupCriterion == null)
                                    groupCriterion = CreateCriterion(model);
                                else
                                    groupCriterion = Expression.Or(groupCriterion, CreateCriterion(model));
                            }

                            //2.分组从数据库取出符合条件的记录
                            IList<T> groupDbModels = EntityMediator<T>.FindAll(groupCriterion);

                            //3.逐个新增或更新
                            foreach (T model in tmpModels)
                            {
                                T dbModel = groupDbModels.FirstOrDefault(CreateFunc(model));
                                if (dbModel != null)
                                {
                                    cntFailed++;
                                    builder.Append(GetExistMessage(model));
                                }
                                else
                                {
                                    result = Save(model);
                                    if (result.IsSucced)
                                    {
                                        cntSucced++;
                                    }
                                    else
                                    {
                                        cntFailed++;
                                        builder.Append(result.Message);
                                    }
                                }
                            }

                            pageIndex++;
                            tmpModels = GetByPage(models, pageIndex, SizePerBatch);
                        }
                        if (cntSucced == 0 && cntFailed > 0)
                        {
                            result.IsSucced = false;
                            result.Message = builder.ToString();
                        }
                        else
                        {
                            result.IsSucced = true;
                            result.Message = builder.ToString() + "成功保存" + cntSucced + "条记录！";
                        }

                        ts.VoteCommit();
                    }
                    catch (Exception ex)
                    {
                        result.IsSucced = false;
                        result.Message = ex.Message;
                        ts.VoteRollBack();
                    }
                }
                #endregion
            }
            return result;
        }

        /// <summary>
        /// 导入
        /// </summary>
        /// <param name="ds"></param>
        /// <returns></returns>
        public virtual OperateResult Import(DataSet ds)
        {
            OperateResult result = new OperateResult();
            if (ds == null || ds.Tables.Count == 0)
            {
                result.IsSucced = false;
                result.Message = "导入的数据为空！";
            }
            else
            {
                List<T> models = DataTableHelper.ConvertTo<T>(ds.Tables[0]);

                if (models != null && models.Count > 0)
                {
                    result = Import(models);
                }
                else
                {
                    result.IsSucced = false;
                    result.Message = "导入的数据为空！";
                }
            }
            return result;
        }


        /// <summary>
        /// 批量新增时需要判断的ICriterion条件
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        protected virtual ICriterion CreateCriterion(T model)
        {
            return Expression.Sql("1<>1");
        }

        /// <summary>
        /// 批量新增时需要判断的Func条件
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        protected virtual Func<T, bool> CreateFunc(T model)
        {
            return m => m.ID == model.ID;
        }

        /// <summary>
        /// 批量更新时需要判断的ICriterion条件
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        protected virtual ICriterion UpdateCriterion(T model)
        {
            return Expression.Eq("ID", model.ID);
        }

        /// <summary>
        /// 批量更新时需要判断的Func条件
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        protected virtual Func<T, bool> UpdateFunc(T model)
        {
            return m => m.ID == model.ID;
        }

        /// <summary>
        /// 获取信息已存在时的提示信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        protected virtual string GetExistMessage(T model)
        {
            return model.ToString() + " 信息已存在";
        }

        #endregion

        /// <summary>
        /// 从集合中分页获取数据
        /// </summary>
        /// <param name="models">数据集合</param>
        /// <param name="pageIndex">目标页码</param>
        /// <param name="pageSize">每页数量</param>
        /// <returns>指定页的数据</returns>
        internal List<T> GetByPage(List<T> models, int pageIndex, int pageSize)
        {
            if (models == null)
            {
                return models;
            }

            List<T> temp = new List<T>();

            int startIndex = (pageIndex - 1) * pageSize;
            int endIndex = pageIndex * pageSize;

            for (int i = startIndex; i < endIndex && i < models.Count; i++)
            {
                temp.Add(models[i]);
            }

            return temp;
        }

        OperateResult Validate(params T[] models)
        {
            OperateResult result = new OperateResult();

            if (models == null || models.Length == 0)
            {
                result.IsSucced = false;
                result.Message = "导入的记录为空！";
            }
            else
            {
                StringBuilder errorBuilder = new StringBuilder();
                int length = models.Length;

                for (int i = 0; i < length; i++)
                {
                    T model = models[i];
                    if (!model.IsValidated)
                    {
                        errorBuilder.Append("第" + (i + 1).ToString() + "行记录：" + model.GetErrorMessage() + " ");
                    }
                }
                result.IsSucced = errorBuilder.Length == 0;
                result.Message = errorBuilder.ToString();
            }
            return result;
        }

        /// <summary>
        /// 从当前应用程序域中获取值
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        protected void SetValue(string name, object value)
        {
            System.Threading.Thread.GetDomain().SetData(name, value);
        }

        /// <summary>
        /// 在当前线程应用程序域中设置值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <returns></returns>
        protected T GetValue<T>(string name)
        {
            T value = default(T);

            object obj = System.Threading.Thread.GetDomain().GetData(name);
            if (obj != null)
                value = (T)obj;

            return value;
        }

        /// <summary>
        /// 获取未删除的数据
        /// </summary>
        /// <returns></returns>
        protected ICriterion GetNotDeletedCriterion()
        {
            return Expression.Eq("IsDeleted", false);
        }

        /// <summary>
        /// 获取机构过滤条件【包含下属机构】
        /// </summary>
        /// <returns></returns>
        protected ICriterion GetOrgansCriertion()
        {
            ICriterion criterion = Expression.Sql("1=1");

            if (ServerApplication.User.IsSuper == false)
            {
                IOrganizationComponent comp = ServerApplication.ComponentFactory.Create<IOrganizationComponent>();
                IList<Organization> list = comp.GetSubOrganization(ServerApplication.Organization, true);


                if (list.Count == 1)
                    criterion = Expression.Eq("Organization", list[0]);
                else
                    criterion = Expression.In("Organization", list.ToArray());
            }
            return criterion;
        }

        /// <summary>
        /// 获取机构过滤条件【不包含下属机构】
        /// </summary>
        /// <returns></returns>
        protected ICriterion GetOrganCriertion()
        {
            return Expression.Eq("Organization", ServerApplication.Organization);
        }
    }
}
